package com.drondea.testclient.panel;

import cn.hutool.core.convert.NumberChineseFormater;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.drondea.sms.session.AbstractClientSessionManager;
import com.drondea.testclient.model.User;
import com.drondea.testclient.service.AbstractTcpService;
import com.drondea.testclient.service.provider.AbstractClientMessageProvider;
import com.drondea.testclient.util.DateTime;
import com.drondea.testclient.util.MobileUtil;
import com.drondea.testclient.util.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.swing.*;
import java.awt.*;
import java.util.Date;

/**
 * @author shd
 * @date 2022/7/18 11:46
 */

@Slf4j
public abstract class AbstractTcpPanel extends AbstractPanel {

    public AbstractClientSessionManager sessionManager;
    
    protected boolean isCanSend = true;
    protected long lastSendCount;
    protected long lastResponseCount;
    protected long lastReportCount;

    public JPanel panel;

    /**
     * 连接信息
     */
    protected JLabel ipLabel;
    protected JLabel portLabel;
    protected JLabel userNameLabel;
    protected JLabel passwordLabel;
    protected JLabel connectCountLabel;
    protected JLabel speedLabel;
    protected JLabel subCodeLabel;
    protected JTextField ipTextField;
    protected JTextField portTextField;
    public JTextField userNameTextField;
    public JTextField passwordTextField;
    protected JTextField connectCountTextField;
    protected JTextField speedTextField;
    public JTextField subCodeTextField;

    /**
     * 短信内容、手机号码
     */
    protected JScrollPane contentScrollPane;
    protected JScrollPane mobileScrollPane;

    /**
     * 按钮：连接，断开，发送，清零
     */
    public JButton connectButton;
    protected JButton disconnectButton;
    public JButton sendButton;
    protected JButton clearButton;

    protected JTextArea contentTextArea;
    /**
     * 字数和条数信息
     */
    protected JLabel msgShowLabel;
    protected JTextArea mobileTextArea;
    protected JCheckBox randomContentCheckBox;
    protected JCheckBox randomMobileCheckBox;
    protected JCheckBox loopSendCheckBox;
    protected JTextField loopSendCountTextField;
    /**
     * 循环发送条数的中文大写
     */
    protected JLabel loopSendCountChineseCap;

    /**
     * 统计信息
     */
    public JLabel connectedCountLabel;
    public JLabel sendCountLabel;
    public JLabel responseCountLabel;
    public JLabel reportCountLabel;
    public JLabel submitSpeedLabel;
    /**
     * 响应速度
     */
    public JLabel responseSpeedLabel;
    /**
     *
     */
    public JLabel reportSpeedLabel;
    /**
     * 平均提交速度
     */
    public JLabel avgSubmitSpeedLabel;
    public JLabel delayGt50msCountLabel;
    public JLabel delayGt100msCountLabel;
    public JLabel delayGt500msCountLabel;
    public JLabel delayGt1sCountLabel;
    public JLabel startTimeLabel;
    public JLabel endTimeLabel;
    public JLabel successCountLabel;
    public JLabel failCountLabel;
    protected User user;

    public void init(int width, int height) {
        panel = new JPanel();
        panel.setLayout(null);

        // 连接信息等输入框
        initText();
        // 按钮添加
        initButton();
        // 内容 手机号 相关
        initInput();
        // 计数相关
        initCount();
        // 坐标
        initComponentBounds(width, height);
    }

    /**
     * 保存接入信息，方便重复使用
     */
    protected abstract void saveConfigInfo();

    /**
     * 创建连接
     */
    protected abstract void connect();

    /**
     * 获取服务
     */
    protected abstract AbstractTcpService getService();

    /**
     * 重置计数
     */
    protected abstract void counterReset();

    private void initCount() {
        connectedCountLabel = new JLabel("当前连接: 0");
        panel.add(connectedCountLabel);

        sendCountLabel = new JLabel("发送数量: 0");
        panel.add(sendCountLabel);

        responseCountLabel = new JLabel("响应数量: 0");
        panel.add(responseCountLabel);

        successCountLabel = new JLabel("提交成功: 0");
        panel.add(successCountLabel);

        failCountLabel = new JLabel("提交失败: 0");
        panel.add(failCountLabel);

        reportCountLabel = new JLabel("报告数量: 0");
        panel.add(reportCountLabel);

        submitSpeedLabel = new JLabel("发送速度: 0/s");
        panel.add(submitSpeedLabel);

        responseSpeedLabel = new JLabel("响应速度: 0/s");
        panel.add(responseSpeedLabel);

        reportSpeedLabel = new JLabel("回执速度: 0/s");
        panel.add(reportSpeedLabel);

        avgSubmitSpeedLabel = new JLabel("平均提交速度: 0/s");
        panel.add(avgSubmitSpeedLabel);

        delayGt50msCountLabel = new JLabel("响应延迟大于50ms: 0");
        panel.add(delayGt50msCountLabel);

        delayGt100msCountLabel = new JLabel("响应延迟大于100ms: 0");
        panel.add(delayGt100msCountLabel);

        delayGt500msCountLabel = new JLabel("响应延迟大于500ms: 0");
        panel.add(delayGt500msCountLabel);

        delayGt1sCountLabel = new JLabel("响应延迟大于1s: 0");
        panel.add(delayGt1sCountLabel);

        startTimeLabel = new JLabel("开始时间:");
        panel.add(startTimeLabel);

        endTimeLabel = new JLabel("结束时间:");
        panel.add(endTimeLabel);

        // 大写提示
        loopSendCountChineseCap = new JLabel("");
        panel.add(loopSendCountChineseCap);
    }

    private void initInput() {
        contentScrollPane = new JScrollPane();
        panel.add(contentScrollPane);

        randomContentCheckBox = new JCheckBox("内容增加随机变量");
        panel.add(randomContentCheckBox);

        randomMobileCheckBox = new JCheckBox("随机手机号码");
        panel.add(randomMobileCheckBox);

        msgShowLabel = new JLabel("当前字数:0,短信条数:0");
        panel.add(msgShowLabel);

        contentTextArea = new JTextArea();
        contentTextArea.addCaretListener(e -> {
            String txt = contentTextArea.getText();
            int leng = txt.length();
            if (randomContentCheckBox.isSelected()) {
                leng += 8;
                txt += "00000000";
            }
            msgShowLabel.setText(StrUtil.format("当前字数:{},短信条数:{}", leng, SignUtil.splitMsg(txt)));
        });
        contentScrollPane.setViewportView(contentTextArea);
        contentTextArea.setText("【庄点科技】我是CMPP测试短信内容");
        contentTextArea.setTabSize(0);
        contentTextArea.setWrapStyleWord(true);
        contentTextArea.setLineWrap(true);

        mobileScrollPane = new JScrollPane();
        panel.add(mobileScrollPane);

        mobileTextArea = new JTextArea();
        mobileScrollPane.setViewportView(mobileTextArea);
        mobileTextArea.setText("17333939565");
        mobileTextArea.setWrapStyleWord(true);
        mobileTextArea.setTabSize(0);
        mobileTextArea.setLineWrap(true);


        loopSendCheckBox = new JCheckBox("循环发送");
        loopSendCheckBox.addChangeListener(e -> loopSendCountTextField.setEditable(loopSendCheckBox.isSelected()));
        panel.add(loopSendCheckBox);

        loopSendCountTextField = new JTextField();
        loopSendCountTextField.setText("100");
        loopSendCountTextField.addCaretListener(e -> {
            String text = loopSendCountTextField.getText();
            if (StrUtil.isNotBlank(text)) {
                loopSendCountChineseCap.setText(NumberChineseFormater.format(Double.parseDouble(text), false));
            } else {
                loopSendCountChineseCap.setText("");
            }
        });
        loopSendCountTextField.setEditable(false);
        panel.add(loopSendCountTextField);
        loopSendCountTextField.setColumns(10);

        clearButton = new JButton("清零");
        clearButton.addActionListener(e -> {
            lastSendCount = 0;
            lastResponseCount = 0;
            lastReportCount = 0;
            sendCountLabel.setText("发送数量: 0");
            responseCountLabel.setText("响应数量: 0");
            successCountLabel.setText("提交成功: 0");
            failCountLabel.setText("提交失败: 0");
            reportCountLabel.setText("报告数量: 0");
            delayGt50msCountLabel.setText("响应延迟大于50ms: 0");
            delayGt100msCountLabel.setText("响应延迟大于100ms: 0");
            delayGt500msCountLabel.setText("响应延迟大于500ms: 0");
            delayGt1sCountLabel.setText("响应延迟大于1s: 0");
            startTimeLabel.setText("开始时间:");
            endTimeLabel.setText("结束时间:");
            avgSubmitSpeedLabel.setText("平均提交速度: 0/s");
            counterReset();
        });
        clearButton.setForeground(Color.BLACK);
        clearButton.setBackground(SystemColor.controlHighlight);
        panel.add(clearButton);
    }

    private void initText() {
        ipLabel = new JLabel("IP");
        ipLabel.setHorizontalAlignment(SwingConstants.RIGHT);
        panel.add(ipLabel);

        ipTextField = new JTextField();
        ipTextField.setText(user.getIp());
        ipTextField.setColumns(10);
        panel.add(ipTextField);

        portLabel = new JLabel("端口");
        portLabel.setHorizontalAlignment(SwingConstants.RIGHT);
        panel.add(portLabel);

        portTextField = new JTextField();
        portTextField.setText(String.valueOf(user.getPort()));
        portTextField.setColumns(10);
        panel.add(portTextField);

        userNameLabel = new JLabel("用户名");
        userNameLabel.setHorizontalAlignment(SwingConstants.RIGHT);
        panel.add(userNameLabel);

        userNameTextField = new JTextField();
        userNameTextField.setText(user.getUsername());
        userNameTextField.setColumns(10);
        panel.add(userNameTextField);

        passwordLabel = new JLabel("密码");
        passwordLabel.setHorizontalAlignment(SwingConstants.RIGHT);
        panel.add(passwordLabel);

        passwordTextField = new JTextField();
        passwordTextField.setText(user.getPassword());
        passwordTextField.setColumns(10);
        panel.add(passwordTextField);

        connectCountLabel = new JLabel("连接数");
        connectCountLabel.setHorizontalAlignment(SwingConstants.RIGHT);
        panel.add(connectCountLabel);

        connectCountTextField = new JTextField();
        connectCountTextField.setText(String.valueOf(user.getConCount()));
        connectCountTextField.setColumns(10);
        panel.add(connectCountTextField);

        speedLabel = new JLabel("速度");
        speedLabel.setHorizontalAlignment(SwingConstants.RIGHT);
        panel.add(speedLabel);

        speedTextField = new JTextField();
        speedTextField.setText(String.valueOf(user.getSubmitSpeed()));
        speedTextField.setColumns(10);
        panel.add(speedTextField);

        subCodeLabel = new JLabel("扩展码");
        subCodeLabel.setHorizontalAlignment(SwingConstants.RIGHT);
        panel.add(subCodeLabel);

        subCodeTextField = new JTextField();
        subCodeTextField.setText("");
        subCodeTextField.setColumns(10);
        panel.add(subCodeTextField);
    }

    private void initButton() {
        connectButton = new JButton("连接");
        connectButton.addActionListener(e -> {
            connect();
            // 禁用 用户名等输入框
            downInput();
        });
        connectButton.setForeground(SystemColor.windowText);
        connectButton.setBackground(SystemColor.controlHighlight);
        panel.add(connectButton);

        disconnectButton = new JButton("断开");
        disconnectButton.addActionListener(e -> {
            // 连接断开
            if (sessionManager != null) {
                sessionManager.doClose();
                AbstractClientMessageProvider messageProvider = (AbstractClientMessageProvider) sessionManager.getMessageProvider();
                messageProvider.destroy();
            }
            upInput();
            isCanSend = false;
            connectButton.setEnabled(true);
            sendButton.setEnabled(false);
        });
        disconnectButton.setForeground(SystemColor.windowText);
        disconnectButton.setBackground(SystemColor.controlHighlight);
        panel.add(disconnectButton);

        sendButton = new JButton("发送");
        sendButton.addActionListener(e -> {
            try {
                send();
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        });
        sendButton.setEnabled(false);
        sendButton.setForeground(Color.BLACK);
        sendButton.setBackground(SystemColor.controlHighlight);
        panel.add(sendButton);

    }

    private void downInput() {
        ipTextField.setEditable(false);
        portTextField.setEditable(false);
        userNameTextField.setEditable(false);
        passwordTextField.setEditable(false);
        connectCountTextField.setEditable(false);
        speedTextField.setEditable(false);
    }

    private void upInput() {
        ipTextField.setEditable(true);
        portTextField.setEditable(true);
        userNameTextField.setEditable(true);
        passwordTextField.setEditable(true);
        connectCountTextField.setEditable(true);
        speedTextField.setEditable(true);
    }

    

    private void send() {
        // 设置开始时间以及清空结束时间
        if ("开始时间:".equals(startTimeLabel.getText())) {
            startTimeLabel.setText(StrUtil.format("开始时间: {}", DateTime.getString(new Date(), DateTime.Y_M_D_H_M_S_S_1)));
        }
        endTimeLabel.setText("结束时间: ");

        boolean manySend = loopSendCheckBox.isSelected();
        if (manySend) {
            new Thread(() -> {
                try {
                    sendButton.setEnabled(false);
                    int manyCount = Integer.parseInt(loopSendCountTextField.getText());
                    for (int i = 0; i < manyCount; i++) {
                        if (!isCanSend) {
                            log.warn("can not send, break!!!");
                            break;
                        }
                        sendMsg();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                sendButton.setEnabled(true);
            }).start();
        } else {
            sendMsg();
        }
    }

    protected void sendMsg() {
        // 短信内容
        String smsContent = contentTextArea.getText().trim();
        boolean randomContent = randomContentCheckBox.isSelected();
        boolean randomMobile = randomMobileCheckBox.isSelected();

        // 随机内容加验证码
        if (randomContent) {
            smsContent += RandomUtil.randomString(8);
        }
        String subCode = StringUtils.defaultString(subCodeTextField.getText(), "");
        // 随机手机号
        if (randomMobile) {
            getService().sendSms(MobileUtil.getMobile("CMPP"), smsContent, subCode);
        } else {
            String mobile = mobileTextArea.getText();
            String[] destMobile = StringUtils.split(mobile, ",");
            for (String tmpMobile : destMobile) {
                if (StrUtil.isBlank(tmpMobile)) {
                    log.warn("当前手机号为空，continue");
                    continue;
                }
                getService().sendSms(tmpMobile, smsContent, subCode);
            }
        }
    }

    public void initComponentBounds(int width, int height) {
        // 连接信息
        ipLabel.setBounds((int) (width * 0.03), (int) (height * 0.05), (int) (width * 0.07), (int) (height * 0.03));
        ipTextField.setBounds((int) (width * 0.11), (int) (height * 0.05), (int) (width * 0.15), (int) (height * 0.04));
        portLabel.setBounds((int) (width * 0.03), (int) (height * 0.13), (int) (width * 0.07), (int) (height * 0.03));
        portTextField.setBounds((int) (width * 0.11), (int) (height * 0.13), (int) (width * 0.15), (int) (height * 0.04));
        userNameLabel.setBounds((int) (width * 0.03), (int) (height * 0.21), (int) (width * 0.07), (int) (height * 0.03));
        userNameTextField.setBounds((int) (width * 0.11), (int) (height * 0.21), (int) (width * 0.15), (int) (height * 0.04));
        passwordLabel.setBounds((int) (width * 0.03), (int) (height * 0.29), (int) (width * 0.07), (int) (height * 0.03));
        passwordTextField.setBounds((int) (width * 0.11), (int) (height * 0.29), (int) (width * 0.15), (int) (height * 0.04));
        connectCountLabel.setBounds((int) (width * 0.03), (int) (height * 0.37), (int) (width * 0.07), (int) (height * 0.03));
        connectCountTextField.setBounds((int) (width * 0.11), (int) (height * 0.37), (int) (width * 0.15), (int) (height * 0.04));
        speedLabel.setBounds((int) (width * 0.03), (int) (height * 0.45), (int) (width * 0.07), (int) (height * 0.03));
        speedTextField.setBounds((int) (width * 0.11), (int) (height * 0.45), (int) (width * 0.15), (int) (height * 0.04));
        subCodeLabel.setBounds((int) (width * 0.03), (int) (height * 0.53), (int) (width * 0.07), (int) (height * 0.03));
        subCodeTextField.setBounds((int) (width * 0.11), (int) (height * 0.53), (int) (width * 0.15), (int) (height * 0.04));

        // 计数统计
        connectedCountLabel.setBounds((int) (width * 0.72), (int) (height * 0.02), (int) (width * 0.20), (int) (height * 0.04));
        sendCountLabel.setBounds((int) (width * 0.72), (int) (height * 0.06), (int) (width * 0.20), (int) (height * 0.04));
        responseCountLabel.setBounds((int) (width * 0.72), (int) (height * 0.12), (int) (width * 0.20), (int) (height * 0.04));
        successCountLabel.setBounds((int) (width * 0.72), (int) (height * 0.16), (int) (width * 0.20), (int) (height * 0.04));
        failCountLabel.setBounds((int) (width * 0.72), (int) (height * 0.21), (int) (width * 0.20), (int) (height * 0.04));
        reportCountLabel.setBounds((int) (width * 0.72), (int) (height * 0.26), (int) (width * 0.20), (int) (height * 0.06));
        submitSpeedLabel.setBounds((int) (width * 0.72), (int) (height * 0.32), (int) (width * 0.20), (int) (height * 0.06));
        responseSpeedLabel.setBounds((int) (width * 0.72), (int) (height * 0.36), (int) (width * 0.20), (int) (height * 0.06));
        reportSpeedLabel.setBounds((int) (width * 0.72), (int) (height * 0.41), (int) (width * 0.20), (int) (height * 0.06));
        avgSubmitSpeedLabel.setBounds((int) (width * 0.72), (int) (height * 0.45), (int) (width * 0.20), (int) (height * 0.06));
        delayGt50msCountLabel.setBounds((int) (width * 0.72), (int) (height * 0.51), (int) (width * 0.20), (int) (height * 0.06));
        delayGt100msCountLabel.setBounds((int) (width * 0.72), (int) (height * 0.55), (int) (width * 0.20), (int) (height * 0.06));
        delayGt500msCountLabel.setBounds((int) (width * 0.72), (int) (height * 0.59), (int) (width * 0.20), (int) (height * 0.06));
        delayGt1sCountLabel.setBounds((int) (width * 0.72), (int) (height * 0.64), (int) (width * 0.20), (int) (height * 0.06));
        startTimeLabel.setBounds((int) (width * 0.72), (int) (height * 0.68), (int) (width * 0.27), (int) (height * 0.06));
        endTimeLabel.setBounds((int) (width * 0.72), (int) (height * 0.72), (int) (width * 0.27), (int) (height * 0.06));
        loopSendCountChineseCap.setBounds((int) (width * 0.28), (int) (height * 0.72), (int) (width * 0.36), (int) (height * 0.04));

        // 按钮相关
        connectButton.setBounds((int) (width * 0.28), (int) (height * 0.03), (int) (width * 0.10), (int) (height * 0.06));
        disconnectButton.setBounds((int) (width * 0.47), (int) (height * 0.03), (int) (width * 0.10), (int) (height * 0.06));
        sendButton.setBounds((int) (width * 0.38), (int) (height * 0.79), (int) (width * 0.10), (int) (height * 0.06));

        // 内容、手机号相关
        contentScrollPane.setBounds((int) (width * 0.28), (int) (height * 0.12), (int) (width * 0.37), (int) (height * 0.22));
        msgShowLabel.setBounds((int) (width * 0.28), (int) (height * 0.34), (int) (width * 0.30), (int) (height * 0.03));
        mobileScrollPane.setBounds((int) (width * 0.28), (int) (height * 0.39), (int) (width * 0.37), (int) (height * 0.16));
        loopSendCheckBox.setBounds((int) (width * 0.28), (int) (height * 0.67), (int) (width * 0.11), (int) (height * 0.04));
        randomContentCheckBox.setBounds((int) (width * 0.28), (int) (height * 0.57), (int) (width * 0.20), (int) (height * 0.04));
        randomMobileCheckBox.setBounds((int) (width * 0.28), (int) (height * 0.62), (int) (width * 0.20), (int) (height * 0.04));
        loopSendCountTextField.setBounds((int) (width * 0.39), (int) (height * 0.67), (int) (width * 0.13), (int) (height * 0.04));
        clearButton.setBounds((int) (width * 0.72), (int) (height * 0.79), (int) (width * 0.10), (int) (height * 0.06));

        for (int i = 0; i < panel.getComponents().length; i++) {
            Font fontTmp = panel.getComponent(i).getFont();
            fontTmp = new Font(fontTmp.getName(), fontTmp.getStyle(), (int) (height * 0.04 * 0.6));
            if (panel.getComponent(i) instanceof JScrollPane) {
                ((JScrollPane) panel.getComponent(i)).getViewport().getView().setFont(fontTmp);
                continue;
            }
            panel.getComponent(i).setFont(fontTmp);
        }
    }
    
}
